package com.cskaoyan.thread02.deadlock.edition2;

/*
        解决思路2:
          如果在实际开发中，加锁顺序不好调整，还有另外一种解决思路：

          如果我们能让一个线程一次成功对它需要的所有锁加锁成功，即
          要么对所需要的锁都加锁成功，要么一把锁都不要加

          意味着将多个锁的加锁变成原子操作

          synchronized（锁对象）{
                // 对lockA锁，和lockB锁加锁
                synchronized() {
                    synchronized() {
                    }
                }
          }


 */
public class Demo1 {
    // lockA锁
    static Object lockA = new Object();
    // lockB锁
    static Object lockB = new Object();

    static Object allLock = new Object();


    public static void main(String[] args) {
        ABThread abThread = new ABThread();
        BAThread baThread = new BAThread();

        abThread.start();
        baThread.start();
    }
}

/*
        先加A锁在加B锁
        1. 先对lockA锁加锁，访问共享变量
        2. 在对lockB锁加锁，访问打印机
 */
class ABThread extends Thread {

    @Override
    public void run() {
        synchronized (Demo1.allLock) {

            synchronized (Demo1.lockA) {
                // 访问共享变量, 计算
                System.out.println("ABThread lockA");
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (Demo1.lockB) {
                    // 访问打印机，打印结果
                    System.out.println("ABThread lockB");
                }
            }
        }
    }
}

/*
        先加B锁在加A锁
        1. 先对lockB锁加锁，先获取打印机的访问
        2. 在对lockA锁加锁，访问共享变量，打印计算结果
  */
class BAThread extends Thread {

    @Override
    public void run() {
       synchronized (Demo1.allLock) {

           synchronized (Demo1.lockB) {
               // 先获取打印机的访问权
               System.out.println("BAThread lockB");
               try {
                   Thread.sleep(50);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               synchronized (Demo1.lockA) {
                   // 访问共享变量，打印计算结果
                   System.out.println("BAThread lockA");
               }
           }
       }
    }
}
